package gttp.nspa.server.dao;

import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;

public class FilterBuilder {

    private CompositeFilterOperator op;
    private List<Filter>            filters;

    public FilterBuilder() {
        this(CompositeFilterOperator.AND);
    }

    public FilterBuilder(CompositeFilterOperator op) {
        this.op = op;
        filters = new ArrayList<>();
    }

    Filter toFilter() {
        int size = filters.size();
        if (size == 0)
            return null;
        if (size == 1)
            return filters.get(0);
        return op.of(filters);
    }

    public FilterBuilder lt(String propertyName, Object value) {
        filters.add(FilterOperator.LESS_THAN.of(propertyName, value));
        return this;
    }

    public FilterBuilder lte(String propertyName, Object value) {
        filters.add(FilterOperator.LESS_THAN_OR_EQUAL.of(propertyName, value));
        return this;
    }

    public FilterBuilder gt(String propertyName, Object value) {
        filters.add(FilterOperator.GREATER_THAN.of(propertyName, value));
        return this;
    }

    public FilterBuilder gte(String propertyName, Object value) {
        filters.add(FilterOperator.GREATER_THAN_OR_EQUAL.of(propertyName, value));
        return this;
    }

    public FilterBuilder eq(String propertyName, Object value) {
        filters.add(FilterOperator.EQUAL.of(propertyName, value));
        return this;
    }

    public FilterBuilder neq(String propertyName, Object value) {
        filters.add(FilterOperator.NOT_EQUAL.of(propertyName, value));
        return this;
    }

    public FilterBuilder in(String propertyName, Object value) {
        filters.add(FilterOperator.IN.of(propertyName, value));
        return this;
    }

    public FilterBuilder and() {
        FilterBuilder fb = new FilterBuilder(CompositeFilterOperator.AND);
        Filter f = toFilter();
        if (f != null)
            fb.filters.add(f);
        return fb;
    }

    public FilterBuilder or() {
        FilterBuilder fb = new FilterBuilder(CompositeFilterOperator.OR);
        Filter f = toFilter();
        if (f != null)
            fb.filters.add(f);
        return fb;
    }

    public Filter build() {
        return toFilter();
    }
}
